using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;

namespace Sucrose.Base
{
    /// <summary>
    /// Facilitates downloading of stuff from the LMS in a queue-based system that handles errors gracefully
    /// </summary>
    public class LMSDownloader
    {
        private Queue<DownloadableItem> items = new Queue<DownloadableItem>();
        private int progressOffset = 0;
        private int itemsComplete = 0;

        public event ProgressUpdateHandler ProgressUpdates;

        /// <summary>
        /// The number that should be added to the total amount of steps in progress
        /// </summary>
        public int ProgressOffset
        {
            get
            {
                return progressOffset;
            }
            set
            {
                progressOffset = value;
            }
        }

        /// <summary>
        /// Sets the number of concurrent downloads
        /// </summary>
        public int ConcurrentDownloads
        {
            get
            {
                try
                {
                    return Settings.GetIntegerValueForKey("ConcurrentDownloads");
                }
                catch (KeyNotFoundException)
                {
                    ConcurrentDownloads = 2;
                    return 2;
                }
            }
            set
            {
                Settings.SetValueAtKey("ConcurrentDownloads", value);
            }
        }

        /// <summary>
        /// Gets the number of items that have been downloaded
        /// </summary>
        public int ItemsComplete
        {
            get
            {
                return itemsComplete;
            }
        }

        /// <summary>
        /// Adds a document to the download queue
        /// </summary>
        /// <param name="item"></param>
        public void AddDocument(DownloadableItem item)
        {
            this.items.Enqueue(item);
        }

        /// <summary>
        /// Downloads documents at the specified rate. Set with ConcurrentDownloads property
        /// </summary>
        public void DownloadDocuments()
        {
            int startingCount = items.Count;
            int concurrentDownloads = ConcurrentDownloads;
            List<Thread> activeThreads = new List<Thread>();

            while(items.Count > 0)
            {
                for (int i = 0; i < Math.Min(concurrentDownloads, items.Count); i++)
                {
                    DownloadableItem item = items.Dequeue();
                    Thread t = new Thread(item.Download);
                    t.Start();
                    activeThreads.Add(t);
                    Logger.Log("Downloading: " + item.Name, MessageType.Info);
                }

                foreach (Thread t in activeThreads)
                {
                    t.Join();

                    if(ProgressUpdates != null)
                        ProgressUpdates(itemsComplete++, startingCount + progressOffset);
                }

                activeThreads.RemoveRange(0, activeThreads.Count);
            }
        }


    }
}
